import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.security.InvalidParameterException;

public class ObjectUtil {

    public static void copyProperties(Object source, Object target, String[] properties) {
        // 1.当properties参数为空数组时，throw java.security.InvalidParameterException 异常
        if (properties == null || properties.length == 0) {
            throw new InvalidParameterException("properties参数为空");
        }

        for (String propertyName : properties) {
            try {
                Field sourceField = source.getClass().getDeclaredField(propertyName);
                Field targetField = target.getClass().getDeclaredField(propertyName);

                // 在source和target中同名但类型不一致时，throw RuntimeException 异常
                if (!sourceField.getType().equals(targetField.getType())) {
                    throw new RuntimeException("类型不一致," + "源类型" + sourceField.getType() + "，目标类型" + targetField.getType());
                }

                sourceField.setAccessible(true);
                targetField.setAccessible(true);

                Object o = sourceField.get(source);
                if (sourceField.getType().isArray()) {
                    // 当属性为数组时
                    Object copiedArray = deepCopyArray(o);
                    targetField.set(target, copiedArray);
                } else {
                    targetField.set(target, sourceField.get(source));
                }
            } catch (NoSuchFieldException | IllegalAccessException e) {
                throw new RuntimeException("拷贝失败 " + propertyName, e);
            }
        }
    }

    private static Object deepCopyArray(Object array) {
        if (array == null) {
            return null;
        }

        Class<?> arrayClass = array.getClass();
        Class<?> componentType = arrayClass.getComponentType();
        int length = Array.getLength(array);
        Object newArray = Array.newInstance(componentType, length);

        if (componentType.isPrimitive()) { // 基本类型
            if (componentType == int.class) {
                int[] intArray = (int[]) array;
                int[] newIntArray = new int[intArray.length];
                System.arraycopy(intArray, 0, newIntArray, 0, intArray.length);
                return newIntArray;
            } else if (componentType == long.class) {
                long[] longArray = (long[]) array;
                long[] newLongArray = new long[longArray.length];
                System.arraycopy(longArray, 0, newLongArray, 0, longArray.length);
                return newLongArray;
            } else if (componentType == float.class) {
                float[] floatArray = (float[]) array;
                float[] newFloatArray = new float[floatArray.length];
                System.arraycopy(floatArray, 0, newFloatArray, 0, floatArray.length);
                return newFloatArray;
            } else if (componentType == double.class) {
                double[] doubleArray = (double[]) array;
                double[] newDoubleArray = new double[doubleArray.length];
                System.arraycopy(doubleArray, 0, newDoubleArray, 0, doubleArray.length);
                return newDoubleArray;
            } else if (componentType == boolean.class) {
                boolean[] booleanArray = (boolean[]) array;
                boolean[] newBooleanArray = new boolean[booleanArray.length];
                System.arraycopy(booleanArray, 0, newBooleanArray, 0, booleanArray.length);
                return newBooleanArray;
            } else if (componentType == char.class) {
                char[] charArray = (char[]) array;
                char[] newCharArray = new char[charArray.length];
                System.arraycopy(charArray, 0, newCharArray, 0, charArray.length);
                return newCharArray;
            } else if (componentType == byte.class) {
                byte[] byteArray = (byte[]) array;
                byte[] newByteArray = new byte[byteArray.length];
                System.arraycopy(byteArray, 0, newByteArray, 0, byteArray.length);
                return newByteArray;
            } else if (componentType == short.class) {
                short[] shortArray = (short[]) array;
                short[] newShortArray = new short[shortArray.length];
                System.arraycopy(shortArray, 0, newShortArray, 0, shortArray.length);
                return newShortArray;
            }
        }

        return newArray;
    }
}